package com.uxsino.simo.indicator.retractor;

import com.uxsino.commons.utils.config.ConfigProp;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;
import com.uxsino.simo.query.QueryTemplate;

import java.util.*;
import java.util.Map.Entry;

// import org.slf4j.Logger;
// import org.slf4j.LoggerFactory;

public class SNMPVLANRetractor extends ListValueRetractor {

    // private static final Logger logger = LoggerFactory.getLogger(SNMPVLANRetractor.class);

    @ConfigProp(name = "size_field")
    public String size_field;

    @ConfigProp(name = "child_field_index")
    public String child_field_index;

    @ConfigProp(name = "child_field")
    public String child_field;

    @ConfigProp(name = "child_group_hex")
    public String child_group_hex;

    @ConfigProp(name = "id_field_key")
    public String id_field_key;

    private Map<Character, Integer> charMap;

    public SNMPVLANRetractor() {
        super();
        charMap = new HashMap<Character, Integer>();
        int num = 0;
        for (char c = '0'; c <= '9'; c++) {
            charMap.put(c, num++);
        }
        charMap.put('a', 10);
        charMap.put('b', 11);
        charMap.put('c', 12);
        charMap.put('d', 13);
        charMap.put('e', 14);
        charMap.put('f', 15);
    }

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        ArrayList<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
        if (obj == null) {
            return records;
        }
        @SuppressWarnings("unchecked")
        Map<String, Map<String, String>> map = (Map<String, Map<String, String>>) obj;

        Set<String> childKeySet = new HashSet<>();
        childKeySet.add(child_field_index);
        childKeySet.add(child_field);

        Map<String, String> childFieldIndexTailMap = prepareChildFieldIndexMap(map);

        Map<String, String> childFieldMap = prepareChildFieldMap(map);

        Map<String, String> sizeMap = map.get(size_field);
        if (sizeMap == null) {
            return records;
        }
        for (Entry<String, String> entry : sizeMap.entrySet()) {
            Map<String, Object> itemMap = new HashMap<>();

            // clean up sign, use last digit as sign
            String key = entry.getKey().trim();
            String sign = key.replace(size_field + ".", "");
            if (sign.endsWith(".")) {
                sign = sign.substring(0, sign.length() - 1);
            }
            String[] tempSign = sign.split("\\.");
            if (tempSign.length > 1) {
                sign = tempSign[tempSign.length - 1];
            }

            itemMap.put(id_field_key, sign);
            for (ColumnEntry columnEntry : columnEntries) {
                if (map.containsKey(columnEntry.index)) {
                    if (!childKeySet.contains(columnEntry.index)) {   // parent fields
                        Map<String, String> innerMap = map.get(columnEntry.index);
                        for (Entry<String, String> innerEntry : innerMap.entrySet()) {

                            String innerKey = innerEntry.getKey();
                            if (innerKey.endsWith(".")) {
                                innerKey = innerKey.substring(0, innerKey.length() - 1);
                            }
                            int e = innerKey.lastIndexOf(".");
                            String tail = innerKey.substring(e + 1);
                            if (tail.equals(sign)) {
                                if (!columnEntry.index.equals(child_group_hex)) {
                                    itemMap.put(columnEntry.field.getName(),
                                        columnEntry.retractor.retract(entity, ctxt, qt, innerEntry.getValue()));

                                } else {
                                    List<String> childSignList = getChildSign(innerEntry.getValue());
                                    List<String> childFieldList = new ArrayList<>();
                                    for (String s : childSignList) {
                                        if (childFieldIndexTailMap.containsKey(s)) {
                                            String childIndex = childFieldIndexTailMap.get(s);
                                            String childField = childFieldMap.getOrDefault(childIndex, null);
                                            if (childField != null) {
                                                childFieldList.add(childField);
                                            }
                                        }
                                    }
                                    for (ColumnEntry ce : columnEntries) {
                                        if (ce.index.equals(child_field)) {
                                            itemMap.put(ce.field.getName(), String.join(",", childFieldList));
                                            break;
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            }
            records.add(itemMap);
        }
        return records;
    }

    // fd:ff:f7:00:00:00:00:00:00:00
    protected List<String> getChildSign(String hexStr) {
        String[] hexArr = hexStr.toLowerCase().split(":");
        List<String> result = new ArrayList<>();
        for (int i = 0; i < hexArr.length; i++) {
            for (int j = 0; j < 2; j++) {
                char c = hexArr[i].charAt(j);
                int num = charMap.get(c);
                for (int k = 3; k >= 0; k--) {
                    int val = ((1 << k) & num) >> k;
                    if (val == 1) {
                        int r = i * 2 * 4 + j * 4 + 4 - k;
                        result.add(String.valueOf(r));
                    }
                }
            }
        }
        return result;
    }

    protected Map<String, String> prepareChildFieldMap(Map<String, Map<String, String>> map) {
        Map<String, String> childFieldMap = new HashMap<>();
        for (Entry<String, String> childEntry : map.get(child_field).entrySet()) {
            String ck = childEntry.getKey();
            if (ck.endsWith(".")) {
                ck = ck.substring(0, ck.length() - 1);
            }
            int cei = ck.lastIndexOf(".");
            String ce = ck.substring(cei + 1);
            childFieldMap.put(ce, childEntry.getValue());
        }
        return childFieldMap;
    }

    protected Map<String, String> prepareChildFieldIndexMap(Map<String, Map<String, String>> map) {
        Map<String, String> childFieldIndexTailMap = new HashMap<>();
        if (map.get(child_field_index) == null) {
            return childFieldIndexTailMap;
        }
        for (Entry<String, String> indexEntry : map.get(child_field_index).entrySet()) {
            String k1 = indexEntry.getKey();
            if (k1.endsWith(".")) {
                k1 = k1.substring(0, k1.length() - 1);
            }
            int ei = k1.lastIndexOf(".");
            String tail = k1.substring(ei + 1);
            childFieldIndexTailMap.put(tail, indexEntry.getValue());
        }
        return childFieldIndexTailMap;
    }

}
